// dh-appointments 云对象 - 预约管理 v3.3 - 2025-11-05 15:02
const db = uniCloud.database();
const _ = db.command;
const { autoMountHospitalId, softDelete, batchSoftDelete, getUserById, getUserList } = require('dh-common');

console.log('✅ dh-appointments 云对象已加载 - v3.3 - 2025-11-05 15:02');

/**
 * 统一响应格式化辅助函数
 */
function formatResponse(code, data = null, message = 'success', extraFields = {}) {
	return {
		code,
		data,
		message,
		success: (code === 200 || code === 201),
		timestamp: Date.now(),
		...extraFields
	};
}

/**
 * 统一错误响应辅助函数
 */
function formatError(error, defaultMessage = '操作失败') {
	console.error('[dh-appointments] 错误:', error);
	return {
		code: 500,
		message: error.message || defaultMessage,
		success: false,
		timestamp: Date.now()
	};
}

/**
 * 辅助函数：生成时间段
 */
function generateTimeSlots(startTime, endTime, slotDuration) {
	const slots = [];
	const startMinutes = timeToMinutes(startTime);
	const endMinutes = timeToMinutes(endTime);
	
	for (let minutes = startMinutes; minutes < endMinutes; minutes += slotDuration) {
		slots.push(minutesToTime(minutes));
	}
	
	return slots;
}

/**
 * 辅助函数：时间转分钟数
 */
function timeToMinutes(time) {
	const [hours, minutes] = time.split(':').map(Number);
	return hours * 60 + minutes;
}

/**
 * 辅助函数：分钟数转时间
 */
function minutesToTime(minutes) {
	const hours = Math.floor(minutes / 60);
	const mins = minutes % 60;
	return `${String(hours).padStart(2, '0')}:${String(mins).padStart(2, '0')}`;
}

/**
 * 辅助函数：更新排班已预约数量
 */
async function updateScheduleBookedSlots(doctorId, date, slotsCount) {
	try {
		const scheduleRes = await db.collection('dh-doctor_schedules')
			.where({
				doctor_id: doctorId,
				schedule_date: date
			})
			.get();
		
		if (scheduleRes.data.length > 0) {
			const schedule = scheduleRes.data[0];
			const newBookedSlots = (schedule.booked_slots || 0) + slotsCount;
			const newAvailableSlots = schedule.total_slots - newBookedSlots;
			
			await db.collection('dh-doctor_schedules').doc(schedule._id).update({
				booked_slots: newBookedSlots,
				available_slots: newAvailableSlots > 0 ? newAvailableSlots : 0
			});
		}
	} catch (error) {
		console.error('更新排班号源失败:', error);
	}
}

/**
 * 内部函数：获取医生某日期的可用时间段
 */
async function _getDoctorAvailableSlots(doctorId, date) {
	try {
		if (!doctorId || !date) {
			return formatResponse(400, null, '医生ID和日期不能为空');
		}
		
		const scheduleRes = await db.collection('dh-doctor_schedules')
			.where({
				doctor_id: doctorId,
				schedule_date: date,
				status: 1
			})
			.get();
		
		if (scheduleRes.data.length === 0) {
			return formatResponse(404, null, '该日期无排班');
		}
		
		const schedule = scheduleRes.data[0];
		const slots = generateTimeSlots(
			schedule.start_time,
			schedule.end_time,
			schedule.slot_duration_minutes
		);
		
		const appointmentsRes = await db.collection('dh-appointments')
			.where({
				'doctor_id._id': doctorId,
				appointment_date: date,
				status: _.in([0, 1, 2])
			})
			.field({
				appointment_time: true,
				duration_minutes: true
			})
			.get();
		
		const bookedSlots = new Set();
		appointmentsRes.data.forEach(apt => {
			const startMinutes = timeToMinutes(apt.appointment_time);
			const duration = apt.duration_minutes || 30;
			const slotsNeeded = Math.ceil(duration / schedule.slot_duration_minutes);
			
			for (let i = 0; i < slotsNeeded; i++) {
				const slotTime = minutesToTime(startMinutes + i * schedule.slot_duration_minutes);
				bookedSlots.add(slotTime);
			}
		});
		
		const availableSlots = slots.map(slot => ({
			time: slot,
			available: !bookedSlots.has(slot)
		}));
		
		return formatResponse(200, {
			schedule_id: schedule._id,
			date: date,
			slot_duration: schedule.slot_duration_minutes,
			slots: availableSlots
		});
	} catch (error) {
		return formatError(error, '获取可用时间段失败');
	}
}

/**
 * 内部函数：检查连续号源是否可用
 */
async function _checkConsecutiveSlots(doctorId, date, startTime, durationMinutes) {
	try {
		if (!doctorId || !date || !startTime || !durationMinutes) {
			return formatResponse(400, null, '参数不完整');
		}
		
		const slotsResult = await _getDoctorAvailableSlots(doctorId, date);
		if (slotsResult.code !== 200) {
			return slotsResult;
		}
		
		const { slots, slot_duration } = slotsResult.data;
		const slotsNeeded = Math.ceil(durationMinutes / slot_duration);
		const startMinutes = timeToMinutes(startTime);
		
		const requiredSlots = [];
		for (let i = 0; i < slotsNeeded; i++) {
			const slotTime = minutesToTime(startMinutes + i * slot_duration);
			requiredSlots.push(slotTime);
		}
		
		const allAvailable = requiredSlots.every(time => {
			const slot = slots.find(s => s.time === time);
			return slot && slot.available;
		});
		
		return formatResponse(200, {
			available: allAvailable,
			required_slots: requiredSlots,
			slots_needed: slotsNeeded
		});
	} catch (error) {
		return formatError(error, '检查号源失败');
	}
}

module.exports = {
	async getAppointmentById(id) {
		try {
			if (!id) {
				return formatResponse(400, null, '预约ID不能为空');
			}
			
			const res = await db.collection('dh-appointments').doc(id).get();
			if (res.data.length === 0) {
				return formatResponse(404, null, '预约不存在');
			}
			
			const appointment = res.data[0];
			
			// 获取患者信息（使用统一的用户查询工具）
			let patientName = '未知用户';
			if (appointment.patient_id) {
				try {
					const userInfo = await getUserById(appointment.patient_id, 'default', true, true);
					if (userInfo) {
						patientName = userInfo.realName || userInfo.displayName || '未知用户';
					}
				} catch (e) {
					console.error('获取患者信息失败:', e);
				}
			}
			
			// 获取医生信息（使用统一的用户查询工具）
			let doctorName = '未知医生';
			if (appointment.doctor_id && appointment.doctor_id._id) {
				try {
					const doctorRes = await db.collection('dh-doctors')
						.doc(appointment.doctor_id._id)
						.field({ user_id: true })
						.get();
					
					if (doctorRes.data && doctorRes.data.length > 0 && doctorRes.data[0].user_id) {
						const userInfo = await getUserById(doctorRes.data[0].user_id, 'default', false, true);
						if (userInfo) {
							doctorName = userInfo.realName || userInfo.displayName || '未知医生';
						}
					}
				} catch (e) {
					console.error('获取医生信息失败:', e);
				}
			}
			
			return formatResponse(200, {
				...appointment,
				patient_name: patientName,
				doctor_name: doctorName
			});
		} catch (error) {
			return formatError(error, '获取预约失败');
		}
	},
	
	async listAppointments(query = {}, skip = 0, limit = 20) {
		try {
			if (typeof query !== 'object' || query === null || Array.isArray(query)) {
				query = {};
			}
		skip = parseInt(skip) || 0;
		limit = parseInt(limit) || 20;
		
		// 默认不显示已删除记录
		query.is_deleted = false;
		
		const res = await db.collection('dh-appointments')
			.where(query)
			.skip(skip)
				.limit(limit)
				.orderBy('appointment_date', 'desc')
				.get();
			
			// 获取患者信息
			const patientIds = [...new Set(res.data.map(item => item.patient_id).filter(id => id))];
			let usersMap = {};
			if (patientIds.length > 0) {
				// 使用统一的用户查询工具批量查询患者信息
				const allPatients = await getUserList({
					includeRoles: ['patient'],
					allowPatients: true,
					format: 'default',
					limit: 1000,
					decryptSensitiveInfo: true
				});
				
				// 构建用户ID到用户信息的映射
				allPatients.forEach(user => {
					if (patientIds.includes(user._id)) {
						usersMap[user._id] = {
							real_name: user.realName || '',
							nickname: user.nickname || '',
							username: user.username || ''
						};
					}
				});
			}
			
			// 获取医生信息
			const doctorIds = [...new Set(res.data.map(item => {
				if (item.doctor_id && typeof item.doctor_id === 'object' && item.doctor_id._id) {
					return item.doctor_id._id;
				}
				return null;
			}).filter(id => id))];
			
			let doctorsMap = {};
			if (doctorIds.length > 0) {
				const doctorsRes = await db.collection('dh-doctors')
					.where({
						_id: _.in(doctorIds)
					})
					.field({
						_id: true,
						user_id: true
					})
					.get();
				
				// 获取医生的用户信息（使用统一的用户查询工具）
				const doctorUserIds = doctorsRes.data.map(d => d.user_id).filter(id => id);
				let doctorUsersMap = {};
				if (doctorUserIds.length > 0) {
					// 使用 getUserList 批量查询医生信息
					const allDoctors = await getUserList({
						includeRoles: ['doctor'],
						format: 'default',
						limit: 1000,
						decryptSensitiveInfo: true
					});
					
					// 构建用户ID到姓名的映射
					allDoctors.forEach(user => {
						if (doctorUserIds.includes(user._id)) {
							doctorUsersMap[user._id] = user.realName || user.displayName || '未知医生';
						}
					});
				}
				
				// 建立医生ID到医生名字的映射
				doctorsRes.data.forEach(doctor => {
					doctorsMap[doctor._id] = doctorUsersMap[doctor.user_id] || '未知医生';
				});
			}
			
			const dataWithUsers = res.data.map(appointment => {
				const userInfo = usersMap[appointment.patient_id];
				const doctorId = appointment.doctor_id && typeof appointment.doctor_id === 'object' ? appointment.doctor_id._id : null;
				const doctorName = doctorId ? (doctorsMap[doctorId] || '暂无') : '暂无';
				
				return {
					...appointment,
					patient_info: userInfo || { real_name: '', nickname: '', username: '' },
					doctor_name: doctorName
				};
			});
			
			return formatResponse(200, dataWithUsers, 'success', { count: dataWithUsers.length });
		} catch (error) {
			return formatError(error, '获取预约列表失败');
		}
	},
	
	async createAppointment(data) {
		try {
			if (!data.patient_id || !data.doctor_id || !data.appointment_date || !data.appointment_time) {
				return formatResponse(400, null, '患者、医生、预约日期和时间不能为空');
			}
			
		let appointmentData = {
			patient_id: data.patient_id,
			patient_name: data.patient_name || '',
			doctor_id: data.doctor_id,
			doctor_name: data.doctor_name || '',
			service_id: data.service_id || '',
			appointment_date: data.appointment_date,
			appointment_time: data.appointment_time,
			duration: data.duration || 30,
			status: data.status || 'pending',
			chief_complaint: data.chief_complaint || '',
			notes: data.notes || '',
			contact_phone: data.contact_phone || '',
			reminder_sent: data.reminder_sent !== undefined ? data.reminder_sent : false,
			cancellation_reason: data.cancellation_reason || '',
			is_deleted: false,  // 软删除字段，默认未删除
			create_time: Date.now(),
			update_time: Date.now()
		};

		// 🏥 自动挂载医院ID（单一医院系统特性）
		appointmentData = await autoMountHospitalId(appointmentData);
			
			const res = await db.collection('dh-appointments').add(appointmentData);
			return formatResponse(201, { _id: res.id }, '预约创建成功');
		} catch (error) {
			return formatError(error, '创建预约失败');
		}
	},
	
	async updateAppointment(id, data) {
		try {
			if (!id) {
				return formatResponse(400, null, '预约ID不能为空');
			}
			
			const updateData = {
				...data,
				update_time: Date.now()
			};
			
			await db.collection('dh-appointments').doc(id).update(updateData);
			return formatResponse(200, null, '预约信息更新成功');
		} catch (error) {
			return formatError(error, '更新预约失败');
		}
	},
	
	async deleteAppointment(id, reason = '') {
		try {
			if (!id) {
				return formatResponse(400, null, '预约ID不能为空');
			}
			
			const uniIdToken = this.getUniIdToken();
			const result = await softDelete('dh-appointments', id, uniIdToken?.uid || '', reason);
			
			if (result.code === 200) {
				return formatResponse(200, null, '预约已移至回收站');
			} else {
				return formatResponse(result.code, null, result.message);
			}
		} catch (error) {
			return formatError(error, '删除预约失败');
		}
	},
	
	async batchUpdateAppointments(updates) {
		try {
			if (!Array.isArray(updates) || updates.length === 0) {
				return formatResponse(400, null, '更新数据不能为空');
			}
			
			const promises = updates.map(item =>
				db.collection('dh-appointments').doc(item._id).update({
					...item,
					update_time: Date.now()
				})
			);
			
			await Promise.all(promises);
			return formatResponse(200, null, `批量更新${updates.length}条记录成功`);
		} catch (error) {
			return formatError(error, '批量更新失败');
		}
	},
	
	async batchDeleteAppointments(ids, reason = '') {
		try {
			if (!Array.isArray(ids) || ids.length === 0) {
				return formatResponse(400, null, 'ID列表不能为空');
			}
			
			const uniIdToken = this.getUniIdToken();
			const result = await batchSoftDelete('dh-appointments', ids, uniIdToken?.uid || '', reason);
			
			return formatResponse(result.code, result.data, result.message);
		} catch (error) {
			return formatError(error, '批量删除失败');
		}
	},
	
	async getPatientAppointments(patientId, skip = 0, limit = 20) {
		try {
			if (!patientId) {
				return formatResponse(400, null, '患者ID不能为空');
			}
			
			const res = await db.collection('dh-appointments')
				.where({ patient_id: patientId })
				.skip(skip)
				.limit(limit)
				.orderBy('appointment_date', 'desc')
				.get();
			
			return formatResponse(200, res.data, 'success', { count: res.data.length });
		} catch (error) {
			return formatError(error, '获取患者预约失败');
		}
	},
	
	async getDoctorAppointments(doctorId, skip = 0, limit = 20) {
		try {
			if (!doctorId) {
				return formatResponse(400, null, '医生ID不能为空');
			}
			
			const res = await db.collection('dh-appointments')
				.where({ doctor_id: doctorId })
				.skip(skip)
				.limit(limit)
				.orderBy('appointment_date', 'desc')
				.get();
			
			return formatResponse(200, res.data, 'success', { count: res.data.length });
		} catch (error) {
			return formatError(error, '获取医生预约失败');
		}
	},
	
	async confirmAppointment(id) {
		try {
			if (!id) {
				return formatResponse(400, null, '预约ID不能为空');
			}
			
			await db.collection('dh-appointments').doc(id).update({
				status: 'confirmed',
				update_time: Date.now()
			});
			
			return formatResponse(200, null, '预约已确认');
		} catch (error) {
			return formatError(error, '确认预约失败');
		}
	},
	
	async cancelAppointment(id, cancellationReason) {
		try {
			if (!id) {
				return formatResponse(400, null, '预约ID不能为空');
			}
			
			await db.collection('dh-appointments').doc(id).update({
				status: 'cancelled',
				cancellation_reason: cancellationReason || '',
				update_time: Date.now()
			});
			
			return formatResponse(200, null, '预约已取消');
		} catch (error) {
			return formatError(error, '取消预约失败');
		}
	},
	
	async completeAppointment(id) {
		try {
			if (!id) {
				return formatResponse(400, null, '预约ID不能为空');
			}
			
			await db.collection('dh-appointments').doc(id).update({
				status: 'completed',
				update_time: Date.now()
			});
			
			return formatResponse(200, null, '预约已完成');
		} catch (error) {
			return formatError(error, '完成预约失败');
		}
	},
	
	async getPatientList() {
		try {
			// 使用统一的用户查询工具查询患者列表
			const patients = await getUserList({
				includeRoles: ['patient'],
				allowPatients: true,
				format: 'default',
				limit: 1000,
				decryptSensitiveInfo: true
			});
			
			const patientList = patients.map(user => {
				const displayName = user.realName || user.displayName || '未命名';
				return {
					value: user._id,
					label: displayName
				};
			});
			
			return formatResponse(200, patientList, 'success', { count: patientList.length });
		} catch (error) {
			return formatError(error, '获取患者列表失败');
		}
	},
	
	async getDoctorScheduleDates(doctorId) {
		try {
			if (!doctorId) {
				return formatResponse(400, null, '医生ID不能为空');
			}
			
			const today = new Date();
			today.setHours(0, 0, 0, 0);
			const todayStr = today.toISOString().split('T')[0];
			
			const res = await db.collection('dh-doctor_schedules')
				.where({
					doctor_id: doctorId,
					schedule_date: _.gte(todayStr),
					status: 1
				})
				.field({
					schedule_date: true,
					available_slots: true,
					total_slots: true
				})
				.orderBy('schedule_date', 'asc')
				.limit(90)
				.get();
			
			const availableDates = res.data
				.filter(item => item.available_slots > 0)
				.map(item => ({
					date: item.schedule_date,
					available_slots: item.available_slots,
					total_slots: item.total_slots
				}));
			
			return formatResponse(200, availableDates, 'success', { count: availableDates.length });
		} catch (error) {
			return formatError(error, '获取排班日期失败');
		}
	},
	
	async getDoctorAvailableSlots(doctorId, date) {
		// 直接调用内部函数
		return await _getDoctorAvailableSlots(doctorId, date);
	},
	
	async checkConsecutiveSlots(doctorId, date, startTime, durationMinutes) {
		// 直接调用内部函数
		return await _checkConsecutiveSlots(doctorId, date, startTime, durationMinutes);
	},
	
	async bookAppointmentWithSlots(appointmentData) {
		try {
			const { patient_id, doctor_id, appointment_date, appointment_time, duration_minutes } = appointmentData;
			if (!patient_id || !doctor_id || !appointment_date || !appointment_time || !duration_minutes) {
				return formatResponse(400, null, '必填字段不能为空');
			}
			
			// 直接调用内部函数，不通过 this
			const checkResult = await _checkConsecutiveSlots(doctor_id, appointment_date, appointment_time, duration_minutes);
			if (checkResult.code !== 200 || !checkResult.data.available) {
				return formatResponse(400, null, '选择的时间段不可用，请重新选择');
			}
			
			// 生成预约号：APT + YYYYMMDD + XXX（当天的序号）
			const dateStr = appointment_date.replace(/-/g, ''); // 2025-11-05 → 20251105
			const todayStart = new Date(appointment_date);
			todayStart.setHours(0, 0, 0, 0);
			const todayEnd = new Date(appointment_date);
			todayEnd.setHours(23, 59, 59, 999);
			
			// 查询当天已有的预约数量
			const todayCountRes = await db.collection('dh-appointments')
				.where({
					appointment_date: appointment_date
				})
				.count();
			
			const todaySequence = (todayCountRes.total || 0) + 1;
			const appointmentNo = `APT${dateStr}${String(todaySequence).padStart(3, '0')}`;
			
			const appointmentRecord = {
				patient_id: patient_id,
				doctor_id: { _id: doctor_id },
				hospital_id: appointmentData.hospital_id ? { _id: appointmentData.hospital_id } : null,
				appointment_no: appointmentNo,
				appointment_date: appointment_date,
				appointment_time: appointment_time,
				duration_minutes: parseInt(duration_minutes),
				visit_type: parseInt(appointmentData.visit_type) || 1,
				chief_complaint: appointmentData.chief_complaint || '',
				diagnosis: appointmentData.diagnosis || '',
				prescription: appointmentData.prescription || '',
				treatment_plan: appointmentData.treatment_plan || '',
				payment_status: parseInt(appointmentData.payment_status) || 0,
				payment_method: parseInt(appointmentData.payment_method) || 0,
				status: parseInt(appointmentData.status) || 1,
				is_deleted: false,  // 软删除字段，默认未删除
				create_time: Date.now(),
				update_time: Date.now()
			};
			
			const res = await db.collection('dh-appointments').add(appointmentRecord);
			await updateScheduleBookedSlots(doctor_id, appointment_date, checkResult.data.slots_needed);
			
			return formatResponse(201, { _id: res.id }, '预约创建成功');
		} catch (error) {
			return formatError(error, '创建预约失败');
		}
	}
};
